【Auth0】Auth0+Apache(mod_auth_openidc)でシングルサインオンしてみる
はじめに
こんにちは植木和樹@上越妙高オフィスです。いろいろなユースケースでAuth0を使ってみています。前回はWordPressにAuth0プラグインをインストールして、ユーザー認証を行ってみました。
今回はApacheからAuth0を扱ってみたいと思います。ApacheとAuth0を組み合わせることで、たとえば社内システムを外部アクセスから保護するためのBasic認証の代わりにAuth0を使ったアクセス制限として利用するということが可能になります。またApacheをリバースプロキシ−として用いれば、Auth0を扱うことが(アプリの改修コストなどで)難しい場合にも最低限のアクセス制限をかけることが可能になるかと思います。
mod_auth_openidcのインストール
Auth0のドキュメントによるとApacheからAuth0を扱うにはmod_auth_openidcというOpenID Connectモジュールリが必要なようです。なお似たような名前でmod_auth_openidというモジュールがありますが別物なのでご注意ください。
Ubuntu/RHEL/CentOSであれば Github pingidentity/mod_auth_openidcからdebやRPMファイルを入手して簡単にインストールすることができるようです。ただ今回はAmazon Linux(2016.09)を利用するため、依存ライブラリの関係でRPMがインストールできませんでした。
とういわけでソースを落としてきてコンパイルしてみることにします。
必要パッケージをインストールする
mod_auth_openidc のINSTALLマニュアルによると下記ライブラリが必要になります。Redisサポートは不要なのでhiredisは使いません。
- Apache (>=2.0)
- cjose (>=0.4.1)
- OpenSSL (>=0.9.8) (>=1.0.1 for Elliptic Curve support)
- Curl (>=?)
- Jansson (>=2.0) (JSON parser for C)
- pcre3 (>=?) (Regular Expressions support)
- pkg-config
mod_auth_openidc/INSTALL at master · pingidentity/mod_auth_openidc
コンパイルするために、gccやautoconf、automakeといったコマンドもインストールしておきましょう。janssonはepelリポジトリにありました。またcjoseはこの後にソースからコンパイルします。 (今回は動作検証を行うためにPHPもインストールしていますが mod_auth_openidc の動作には不要です)
sudo yum install autoconf automake gcc httpd24 httpd24-devel libcurl-devel openssl-devel pcre-devel -y sudo yum install php56 -y sudo yum install --enablerepo=epel jansson jansson-devel -y
インストールされたバージョンは下記の通りです。
- Apache 2.4.23
- openssl-1.0.1k
- curl-7.47.1
- jansson-2.9-1
- pcre-8.21
- pkgconfig-0.27.1
cjose をコンパイルする
からcjose-0.4.1.tar.gzをダウンロードしてコンパイルします。ライブラリは/usr/lib64にインストールしてpkg-configから見つけられるようにしています。
$ curl -OL https://github.com/pingidentity/mod_auth_openidc/releases/download/v2.1.3/cjose-0.4.1.tar.gz $ tar xvzf cjose-0.4.1.tar.gz $ cd cjose-0.4.1 $ ./configure --prefix=/usr --libdir=/usr/lib64 $ make $ sudo make install
mod_auth_openidc をコンパイルする
cjoseと同様 Releases · pingidentity/mod_auth_openidc からSource code (tar.gz)(v2.1.3.tar.gz)をダウンロードしてコンパイルします。
$ curl -OL https://github.com/pingidentity/mod_auth_openidc/archive/v2.1.3.tar.gz $ tar xvzf v2.1.3.tar.gz $ cd mod_auth_openidc-2.1.3 $ ./autogen.sh $ ./configure --prefix=/usr $ make $ sudo make install
Auth0 Client設定
mod_auth_openidcモジュール設定の前に、ApacheからAuth0へ接続するためのClient設定を行います。
Auth0のダッシュボードからClients - CREATE CLIENTをクリックすると新規クライアント作成画面が開くので、クライアント名を入力し、Client TypeとしてNon Interactive Clientsを選択してCREATEします。
Clientが作成できたらSettingsタブからClient ID, Client Secretをメモしておきましょう。またAllowed Callback URLsには、Auth0での認証完了後に戻したい先のURLを記入します。
認証ソース(Connections)は前回同様Google Apps認証のみを利用することにします。
mod_auth_openidcの設定
最後にmod_auth_openidcモジュールの設定を行います。サンプルの設定は下記ページからコピーできます。
/etc/httpd/conf.d/openidc.conf
LoadModule auth_openidc_module modules/mod_auth_openidc.so OIDCProviderIssuer https://<your-auth0-account>.auth0.com OIDCProviderAuthorizationEndpoint https://<your-auth0-account>.auth0.com/authorize OIDCProviderTokenEndpoint https://<your-auth0-account>.auth0.com/oauth/token OIDCProviderTokenEndpointAuth client_secret_post OIDCProviderUserInfoEndpoint https://<your-auth0-account>.auth0.com/userinfo OIDCClientID < your-client-id > OIDCClientSecret < your-client-secret > OIDCProviderJwksUri https://<your-auth0-account>.auth0.com/.well-known/jwks.json OIDCScope "openid name email" OIDCRedirectURI https://example.com/protect/redirect/ OIDCCryptoPassphrase hogehoge OIDCCookiePath / #SSLはELBでTerminationするのでコメントアウトします #SSLEngine on #SSLCertificateFile /home/your_cert.crt #SSLCertificateKeyFile /home/your_key.key <Location /protect/> AuthType openid-connect Require valid-user LogLevel debug </Location>
OIDCClientID, OIDCClientSecretにはAuth0のSettingsページでメモしておいた文字列を書きます。またOIDCRedirectURIにはAllowed Callback URLsで記入したURLを入れましょう。
設定ファイルを保存したらhttpdをリスタートしておきましょう。
$ httpd -t Syntax OK $ sudo service httpd restart
動作確認
ブラウザでサーバーにアクセスしてみます。が、その前にどんなリクエストがやりとりされているのか見てみたいのでphpinfo()を出力するページを用意します。
$ sudo -s # echo '<?php phpinfo() ?>' | tee -a /var/www/html/index.php # mkdir -p /var/www/html/protect/redirect # cp -p /var/www/html/index.php /var/www/html/protect/ # cp -p /var/www/html/index.php /var/www/html/protect/redirect/
ブラウザでサーバーにアクセスしましょう。 https://example.com/ トップページはアクセス制限をかけていないので認証なしで表示することができます。
次に保護されたURLにアクセスしてみます。 https://example.com/protect/ するとAuth0のログインぺージにリダイレクトされます。Google Appsによる認証を選択します。
認証が完了すると元々アクセスしていたパス /protect/ を表示することができました! Apacheの変数にOIDCで始まる値が設定されていることが分かりますね。
なおブラウザからは分かりませんがGoogle Appsによる認証選択後に、ApacheのCallback URL(https://example.com/protect/redirect/)へのリダイレクトが行われ、Apache→Auth0へアクセスするための認証情報が渡されていることがわかりました(Apacheのアクセスログで確認できます)。
またこの認証情報を用いてApache(mod_auth_oidc)からAuth0へアクセスされていました。(Auth0のログ参照画面で確認できます)
補足情報
1: OIDCRedirectURI について
OIDCRedirectURIはAuth0側の認証が完了するとブラウザがリダイレクトされる先になります。リダイレクト時のURLパラメータとしてApacheがAuth0へアクセスするための認証情報が渡されてきます。 このURL自体はApacheがリクエストを受けた際にmod_auth_openidcがトラップして処理するので、特にファイル等を用意する必要はありません。
ただしOIDCRedirectURIのパスはアクセス制限されたパス以下でないといけないようです。例えば今回は<Location>タグで/protect/にアクセス制限をかけています。その場合在OIDCRedirectURIはそのパス配下/protect/redirect/にする必要があります。
またAuth0のCallback URLsと合わせておかないと認証後にエラーが表示されます。
2: OIDCCryptoPassphrase について
OIDCCryptoPassphraseに設定するパスフレーズはAuth0とは関係なく任意のもので良いようです。このパスワードはCookie等を暗号化するために使われるようです。
3. 認証セッションの有効期限について
一度認証が通るとAuth0で設定したJWT Expiration (seconds)(初期値: 36000秒 = 10時間)は再認証なしでページが表示できます。ただしApacheを再起動するとサーバー側の認証情報が消去されてしまうため再度認証が必要になります。
簡易的にApacheを再起動してもセッションを継続したい場合は設定ファイルでCacheTypeをFileにすればOKです。
OIDCCacheType file
またローカルファイルだと、複数のサーバーでApacheを冗長化させた時に情報が共有されません。スケールアウトする環境で使う場合はMemcached/Redisなどを検討した方が良さそうです。
まとめ
今回はApacheを使ってAuth0での認証をやってみました。Amazon LinuxだとRPMが提供されていないため準備がやや複雑になってしまいましたが、Ubuntuを採用して認証専用サーバーとして分離させてあげればより簡単に導入ができるかと思います。
また認証セッションの共有についても、AWSならElastiCacheを使ってRedisも簡単に導入できるので今後試してみたいと思います。